home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / smaltalk / manchest.lha / MANCHESTER / usenet / st80_pre4 / grapher / grapher-1.st < prev    next >
Text File  |  1993-07-24  |  33KB  |  1,244 lines

  1. "    NAME        grapher-1
  2.     AUTHOR        usenet
  3.     FUNCTION    ?
  4.     ST-VERSION    ?
  5.     PREREQUISITES    
  6.     CONFLICTS
  7.     DISTRIBUTION    world
  8.     VERSION        1
  9.     DATE    17 Sep 1986"
  10. ScrollController subclass: #XAxisScrollController
  11.     instanceVariableNames: 'xScrollBar xMarker xSavedArea '
  12.     classVariableNames: ''
  13.     poolDictionaries: ''
  14.     category: 'Grapher'!
  15. XAxisScrollController comment:
  16. 'I represent control for scrolling using an x-axis scroll bar.  I am a subclass of ScrollController that creates an x-axis scroll bar.  My subclasses then have x and y-axis
  17. scroll bars.  I keep control as long as the cursor is inside the view or either one of the scroll bars.
  18.  
  19. The y-axis scroll bar is a rectangular area representing the length of the information being viewed.  It contains an inner rectangle whose top y-coordinate represents the relative position of the information visible on the screen with respect to all of the information, and whose size represents the relative amount of that information visible on the screen.  The user controls which part of the information is visible by pressing the red button.  If the cursor is to the right of the inner rectangle, the windo
  20.  
  21.  
  22.  
  23. w onto the visible information moves upward, if the cursor is to the left, the window moves downward, and if the cursor is inside, the inner rectangle is grabbed and moved to a desired position.  The x-axis scroll bar is controlled in an analogous manner.  
  24.  
  25. Instance Variables:
  26.     xScrollBar    <Quadrangle> inside white, the outer rectangle
  27.     xMarker        <Quadrangle> inside gray, the inner rectangle
  28.     xSavedArea    <Form> the area the xScrollBar overlaps, restored whenever
  29.                 the xScrollBar is hidden
  30.     '!
  31.  
  32.  
  33. !XAxisScrollController methodsFor: 'initialize-release'!
  34.  
  35. initialize
  36.     super initialize.
  37.     xScrollBar _ Quadrangle new.
  38.     xScrollBar borderWidthLeft: 2 right: 2 top: 0 bottom: 2.
  39.     xMarker _ Quadrangle new.
  40.     xMarker insideColor: Form gray! !
  41.  
  42.  
  43. !XAxisScrollController methodsFor: 'basic control sequence'!
  44.  
  45. controlInitialize
  46.     "The scrollbar has a two-pixel border, and for alignment it assumes that this sub-view
  47.     has a one-pixel border and shares another one-pixel border from its neighbor/super view"
  48.     super controlInitialize.
  49.     xScrollBar region: (0 @ 0 extent: (view displayBox width + 2) @ 32). 
  50.     xMarker region: self computeXMarkerRegion.
  51.     xScrollBar _ xScrollBar align: xScrollBar topLeft with: view displayBox bottomLeft - (1@0).
  52.     xMarker _ xMarker align: xMarker leftCenter with: xScrollBar inside leftCenter.
  53.     xSavedArea _ Form fromDisplay: xScrollBar.
  54.     xScrollBar displayOn: Display.
  55.     self moveXMarker!
  56.  
  57. controlTerminate
  58.     super controlTerminate.
  59.     xSavedArea notNil     
  60.         ifTrue: 
  61.             [xSavedArea displayOn: Display at: xScrollBar topLeft.
  62.             xSavedArea_ nil]! !
  63.  
  64.  
  65. !XAxisScrollController methodsFor: 'control defaults'!
  66.  
  67. controlActivity
  68.  
  69.     self xScrollBarContainsCursor
  70.         ifTrue: [self xScroll]
  71.         ifFalse: [super controlActivity]!
  72.  
  73. isControlActive
  74.  
  75.     ^self xScrollBarContainsCursor or: [super isControlActive]! !
  76.  
  77.  
  78. !XAxisScrollController methodsFor: 'scroll bar region'!
  79.  
  80. repaintUnderScrollBar
  81.     "Repaint the area under the scroll bar ."
  82.  
  83.     super repaintUnderScrollBar.
  84.     self repaintUnderXScrollBar!
  85.  
  86. repaintUnderXScrollBar
  87.     "Repaint the area under the scroll bar ."
  88.  
  89.     xSavedArea notNil     
  90.         ifTrue: 
  91.             [xSavedArea displayOn: Display at: xScrollBar topLeft.
  92.             xSavedArea_ nil]! !
  93.  
  94.  
  95. !XAxisScrollController methodsFor: 'scrolling'!
  96.  
  97. canXScroll
  98.     "Answer whether there is information that is not visible and can be seen
  99.     by scrolling."
  100.     ^xMarker region width < xScrollBar inside width!
  101.  
  102. scrollViewLeft
  103.     "Scroll the receiver's view left the default amount."
  104.     self xScrollView: self xScrollAmount negated!
  105.  
  106. scrollViewNoDisplay: delta
  107.  
  108.     | t2 |
  109.     delta ~= 0
  110.         ifTrue: 
  111.             [t2 _ (delta min: view window top - model boundingBox top)
  112.                         max: view window top - model boundingBox bottom.
  113.             view scrollBy: 0 @ t2]!
  114.  
  115. scrollViewRight
  116.     "Scroll the receiver's view right the default amount."
  117.     self xScrollView: self xScrollAmount!
  118.  
  119. viewXDelta
  120.     "Answer an integer that indicates how much the view should be scrolled.
  121.     The scroll bar has been moved and now the view must be so the amount to
  122.     scroll is computed as a ratio of the current scroll bar position."
  123.  
  124.     ^view window left - view boundingBox left -
  125.         ((xMarker left - xScrollBar inside left) asFloat /
  126.             xScrollBar inside width asFloat *
  127.                 view boundingBox width asFloat) rounded!
  128.  
  129. xScroll
  130.     "Check to see whether the user wishes to jump, scroll left, or scroll right."
  131.  
  132.     | savedCursor regionPercent |
  133.     savedCursor _ sensor currentCursor.
  134.     [self xScrollBarContainsCursor]
  135.         whileTrue: 
  136.             [Processor yield.
  137.             regionPercent _ 100 * (xScrollBar inside bottom  - sensor cursorPoint y) // xScrollBar height.
  138.             regionPercent <= 40
  139.                 ifTrue: [self scrollLeft]
  140.                 ifFalse: [regionPercent >= 60
  141.                             ifTrue: [self scrollRight]
  142.                             ifFalse: [self xScrollAbsolute]]].
  143.     savedCursor show!
  144.  
  145. xScrollAmount
  146.     "Answer the number of bits of x-coordinate should be scrolled.  This is a 
  147.     default determination based on the view's preset display transformation."
  148.  
  149.     ^((view inverseDisplayTransform: sensor cursorPoint)
  150.         - (view inverseDisplayTransform: xScrollBar inside leftCenter)) x!
  151.  
  152. xScrollView
  153.     "The scroll bar jump method was used so that the view should be updated to
  154.     correspond to the location of the scroll bar gray area."
  155.     self xScrollView: self viewXDelta!
  156.  
  157. xScrollView: anInteger 
  158.     "If anInteger is not zero, tell the receiver's view to scroll by anInteger amount."
  159.  
  160.     anInteger ~= 0
  161.         ifTrue: 
  162.             [view scrollBy: ((anInteger min: view window left - view boundingBox left)
  163.                         max: view window left - view boundingBox right) @ 0.
  164.             view clearInside.
  165.             view display]! !
  166.  
  167.  
  168. !XAxisScrollController methodsFor: 'cursor'!
  169.  
  170. xMarkerContainsCursor
  171.     "Answer whether the gray area inside the scroll bar area contains the cursor."
  172.     ^xMarker inside containsPoint: sensor cursorPoint!
  173.  
  174. xScrollBarContainsCursor
  175.     "Answer whether the cursor is anywhere within the scroll bar area."
  176.     ^xScrollBar inside containsPoint: sensor cursorPoint! !
  177.  
  178.  
  179. !XAxisScrollController methodsFor: 'marker adjustment'!
  180.  
  181. computeXMarkerRegion
  182.     "Answer the rectangular area in which the gray area of the scroll bar
  183.     should be displayed."
  184.  
  185.     ^0@0 extent: ((view window width asFloat /
  186.                         view boundingBox width *
  187.                             xScrollBar inside width)
  188.                  rounded min: xScrollBar inside width) @ 10!
  189.  
  190. moveXMarker
  191.     "The view window has changed.  Update the xMarker."
  192.  
  193.     self moveXMarker: self xMarkerDelta negated!
  194.  
  195. moveXMarker: anInteger
  196.     "Update the xMarker so that is is translated by an amount corresponding to
  197.     a distance of anInteger, constrained within the boundaries of the scroll bar."
  198.  
  199.     Display fill: xMarker mask: xScrollBar insideColor.
  200.     xMarker _ xMarker translateBy: ((anInteger min: xScrollBar inside right - xMarker right) max:
  201.                     xScrollBar inside left - xMarker left) @ 0.
  202.     xMarker displayOn: Display!
  203.  
  204. xMarkerDelta
  205.     ^xMarker left 
  206.         - xScrollBar inside left  
  207.         - ((view window left - view boundingBox left) asFloat 
  208.             / view boundingBox width asFloat *
  209.                 xScrollBar inside width asFloat) rounded!
  210.  
  211. xMarkerRegion: aRectangle 
  212.     "Set the area defined by aRectangle as the xMarker.  Fill it with gray tone."
  213.  
  214.     Display fill: xMarker mask: xScrollBar insideColor.
  215.     xMarker region: aRectangle.
  216.     xMarker _ xMarker align: xMarker leftCenter with: xScrollBar inside leftCenter! !
  217.  
  218.  
  219. !XAxisScrollController methodsFor: 'private'!
  220.  
  221. scrollLeft
  222.     "This is modified from the original to provide continuous scrolling"
  223.     self changeCursor: Cursor left.
  224.     sensor anyButtonPressed 
  225.         ifTrue: [self canXScroll
  226.                     ifTrue: 
  227.                         [self scrollViewLeft.
  228.                         self moveXMarker]].
  229.     sensor waitNoButton!
  230.  
  231. scrollRight
  232.     "This is modified from the original to provide continuous scrolling"
  233.     self changeCursor: Cursor right.
  234.     sensor anyButtonPressed
  235.         ifTrue: [self canXScroll
  236.                     ifTrue: 
  237.                         [self scrollViewRight.
  238.                         self moveXMarker]].
  239.     sensor waitNoButton!
  240.  
  241. xAndYScrollAbsolute
  242.  
  243.     | oldMarker oldXMarker savedCursor |
  244.     (((self canXScroll) or: [self canScroll])
  245.             and: [sensor redButtonPressed]) ifTrue:
  246.         [savedCursor _ sensor currentCursor.
  247.         self changeCursor: Cursor fourWay.
  248.         [sensor redButtonPressed] whileTrue:
  249.             [oldMarker _ marker.
  250.             oldXMarker _ xMarker.
  251.             marker _ marker translateBy:
  252.                 0@((sensor cursorPoint y - marker center y
  253.                         min: scrollBar inside bottom - marker bottom)
  254.                             max: scrollBar inside top - marker top).
  255.             xMarker _ xMarker translateBy:
  256.                 ((sensor cursorPoint x - xMarker center x
  257.                     min: xScrollBar inside right - xMarker right)
  258.                         max: xScrollBar inside left - xMarker left) @ 0.
  259.             (oldMarker areasOutside: marker),
  260.             (marker areasOutside: oldMarker),
  261.             (oldXMarker areasOutside: xMarker),
  262.             (xMarker areasOutside: oldXMarker) do:
  263.                 [:region | Display fill: region rule: Form reverse mask: Form gray].
  264.             self scrollViewNoDisplay: self viewDelta.
  265.             self xScrollView.
  266.             scrollBar display.
  267.             xScrollBar display.
  268.             self moveMarker.
  269.             self moveXMarker].
  270.         savedCursor show]!
  271.  
  272. xScrollAbsolute
  273.     | oldMarker |
  274.     self changeCursor: Cursor xMarker.
  275.     self canXScroll & sensor anyButtonPressed ifTrue:
  276.         [[sensor anyButtonPressed] whileTrue:
  277.             [oldMarker _ xMarker.
  278.             xMarker _ xMarker translateBy:
  279.                 ((sensor cursorPoint x - xMarker center x min:
  280.                     xScrollBar inside right - xMarker right) max: xScrollBar inside left - xMarker left) @ 0.
  281.             (oldMarker areasOutside: xMarker), (xMarker areasOutside: oldMarker) do:
  282.                 [:region | Display fill: region rule: Form reverse mask: Form gray]].
  283.             self xScrollView.
  284.             xScrollBar display.
  285.             self moveXMarker]! !
  286. XAxisScrollController subclass: #GraphHolderController
  287.     instanceVariableNames: 'scrollBox selection selectionMenu '
  288.     classVariableNames: 'YellowButtonMenu '
  289.     poolDictionaries: ''
  290.     category: 'Grapher'!
  291. GraphHolderController comment:
  292. 'As a subclass of XAxisScrollController I provide X and Y axis scrolling.  In addition, I provide ''smooth'' scrolling by red button dragging of the mouse.  I also am capable of responding to red button clicks to select an element of the display if I have a menu to activate for selections.  The menu is initialized by my selectionMenu: message which takes an ActionMenu as its argument. The message selectors included with the ActionMenu must be messages that the objects which make up the graph respond to.
  293.  
  294. My instance variables:
  295.  
  296.     scrollBox    <Rectangle>
  297.                 My scrollBox represents the area of the display which
  298.                 is visible on the screen.  It is in local view coordinates.
  299.     selection    <GraphNode>
  300.                 If an element of the display has been selected by clicking
  301.                 the mouse red button on it, it is saved here.
  302.     selectionMenu <Array of (PopUpMenu, Array of message selectors)>
  303.                 The yellow button menu to be activated when a selection
  304.                 has been made and the yellow button is pressed.  Menu
  305.                 messages are sent to the object field of the selected
  306.                 GraphNode.  If selectionMenu is nil the window does not
  307.                 respond to red button clicks (although red button scrolling
  308.                 is still available).
  309.  
  310. '!
  311.  
  312.  
  313. !GraphHolderController methodsFor: 'initialize-release'!
  314.  
  315. initialize
  316.     "I use an ActionMenu rather than a PopUpMenu so no
  317.     yellowButtonMessages are needed."
  318.  
  319.     yellowButtonMenu _ YellowButtonMenu.
  320.     scrollBox _ 0@0 extent: 0@0.
  321.     super initialize! !
  322.  
  323.  
  324. !GraphHolderController methodsFor: 'accessing'!
  325.  
  326. scrollBox: aRectangle
  327.     "My scrollBox is a Rectangle which pans over the virtual display of
  328.     my model.  My view looks through my scrollBox at the model.  Normally,
  329.     my window would perform this function, but windows get scaled and
  330.     I required an unscaled scrollBox."
  331.  
  332.     scrollBox _ Rectangle origin: 0@0 extent: aRectangle extent!
  333.  
  334. selection
  335.  
  336.     ^selection!
  337.  
  338. selectionMenu: anActionMenu
  339.  
  340.     selectionMenu _ anActionMenu! !
  341.  
  342.  
  343. !GraphHolderController methodsFor: 'basic control sequence'!
  344.  
  345. controlInitialize
  346.  
  347.     selection == nil ifFalse: [self darkHighlightSelection].
  348.     super controlInitialize!
  349.  
  350. controlTerminate
  351.  
  352.     selection == nil ifFalse: [self dimHighlightSelection]. 
  353.     super controlTerminate! !
  354.  
  355.  
  356. !GraphHolderController methodsFor: 'control defaults'!
  357.  
  358. controlActivity
  359.  
  360.     | cursorPoint xlate newSelection |
  361.     sensor redButtonPressed ifTrue:
  362.         [sensor leftShiftDown | (selectionMenu == nil)
  363.             ifTrue: [^self xAndYScrollAbsolute].
  364.         cursorPoint _ (sensor cursorPoint
  365.                             translateBy: scrollBox origin
  366.                                         - view displayTransformation translation
  367.                                         - model offset) rounded.
  368.         newSelection _ model selectNodeAt: cursorPoint.
  369.         self setSelection: newSelection.
  370.         newSelection == nil
  371.             ifTrue: [self xAndYScrollAbsolute]
  372.             ifFalse: [[sensor redButtonPressed & self isControlActive]
  373.                         whileTrue]].
  374.     super controlActivity!
  375.  
  376. isControlActive
  377.  
  378.     ^sensor blueButtonPressed not and: [super isControlActive]! !
  379.  
  380.  
  381. !GraphHolderController methodsFor: 'menu messages'!
  382.  
  383. fileOutGraph
  384.     "Produce a PostScript file which will make a hardcopy version of my model."
  385.  
  386.     | aStream |
  387.     Cursor write showWhile:
  388.         [aStream _ FileStream fileNamed: 'diagps.script'.
  389.         model psStoreOn: aStream.
  390.         aStream close]!
  391.  
  392. localMenuItem: aSelector
  393.  
  394.     ^ #( #mvcInspect #fileOutGraph ) includes: aSelector!
  395.  
  396. menuMessageReceiver
  397.  
  398.     selection == nil
  399.         ifTrue: [^self]
  400.         ifFalse: [sensor leftShiftDown
  401.             ifTrue: [^selection]
  402.             ifFalse: [^selection object]]!
  403.  
  404. mvcInspect
  405.  
  406.     self controlTerminate.
  407.     sensor leftShiftDown
  408.         ifTrue: [view superView inspect]
  409.         ifFalse: [view inspect]!
  410.  
  411. yellowButtonActivity
  412.     "Determine which item in the yellow button pop-up menu is selected.
  413.     If one is selected, then send the corresponding message to the object
  414.     designated as the menu message receiver."
  415.  
  416.     | index selector |
  417.     yellowButtonMenu == nil
  418.         ifFalse: 
  419.             [index _ yellowButtonMenu startUpYellowButton.
  420.             index ~= 0 
  421.                 ifTrue:
  422.                     [selector _ yellowButtonMenu selectorAt: index.
  423.                     (self localMenuItem: selector)
  424.                         ifTrue: [self perform: selector]
  425.                         ifFalse: [self controlTerminate.
  426.                                 selector numArgs = 1
  427.                                     ifTrue: [self menuMessageReceiver perform: selector with: model]
  428.                                     ifFalse: [self menuMessageReceiver perform: selector].
  429.                                 self controlInitialize]]]! !
  430.  
  431.  
  432. !GraphHolderController methodsFor: 'marker adjustment'!
  433.  
  434. computeMarkerRegion
  435.  
  436.     ^Rectangle
  437.         origin: 0 @ 0
  438.         extent: 10 @ ((scrollBox height asFloat /
  439.                             view boundingBox height asFloat *
  440.                                 scrollBar inside height) rounded
  441.                         min: scrollBar inside height)!
  442.  
  443. computeXMarkerRegion
  444.  
  445.     ^Rectangle
  446.         origin: 0 @ 0
  447.         extent: ((scrollBox width asFloat /
  448.                             view boundingBox width asFloat *
  449.                                 xScrollBar inside width) rounded
  450.                         min: xScrollBar inside width) @ 10!
  451.  
  452. markerDelta
  453.     ^marker top
  454.         - scrollBar inside top
  455.         - (scrollBox top - view boundingBox top asFloat 
  456.             / view boundingBox height asFloat *
  457.                 scrollBar inside height asFloat) rounded!
  458.  
  459. xMarkerDelta
  460.     ^xMarker left 
  461.         - xScrollBar inside left  
  462.         - (scrollBox left - view boundingBox left asFloat 
  463.             / view boundingBox width asFloat
  464.             * xScrollBar inside width asFloat) rounded! !
  465.  
  466.  
  467. !GraphHolderController methodsFor: 'scrolling'!
  468.  
  469. scrollAmount
  470.  
  471.     ^(sensor cursorPoint - scrollBar inside topCenter) y!
  472.  
  473. scrollBy: amount
  474.  
  475.     scrollBox _ scrollBox translateBy: amount!
  476.  
  477. scrollView: anInteger 
  478.     "If anInteger is not zero, scroll by anInteger amount."
  479.  
  480.     | min max amount |
  481.     max _ view boundingBox top - scrollBox top min: 0.
  482.     min _ view boundingBox bottom - scrollBox bottom max: 0.
  483.     amount _ (anInteger negated max: max) min: min.
  484.     amount ~= 0
  485.         ifTrue: 
  486.             [self scrollBy: 0 @ amount.
  487.             view clearInside.
  488.             view display]!
  489.  
  490. scrollViewNoDisplay: anInteger 
  491.  
  492.     | min max amount |
  493.     max _ view boundingBox top - scrollBox top min: 0.
  494.     min _ view boundingBox bottom - scrollBox bottom max: 0.
  495.     amount _ (anInteger negated max: max) min: min.
  496.     amount ~= 0
  497.         ifTrue: 
  498.             [self scrollBy: 0 @ amount]!
  499.  
  500. scrollViewXY: aPoint 
  501.  
  502.     | amount ymax ymin xmax xmin |
  503.     ymax _ view boundingBox top - scrollBox top min: 0.
  504.     ymin _ view boundingBox bottom - scrollBox bottom max: 0.
  505.     xmax _ view boundingBox left - scrollBox left min: 0.
  506.     xmin _ view boundingBox right - scrollBox right max: 0.
  507.     amount _ Point x: ((aPoint x negated max: xmax) min: xmin) rounded
  508.                     y: ((aPoint y negated max: ymax) min: ymin) rounded.
  509.     amount ~= (0@0)
  510.         ifTrue: 
  511.             [self scrollBy: amount.
  512.             view clearInside.
  513.             view display]!
  514.  
  515. viewDelta
  516.     "Answer an integer that indicates how much the view should be scrolled.
  517.     The scroll bar has been moved and now the view must be so the amount to
  518.     scroll is computed as a ratio of the current scroll bar position."
  519.  
  520.     ^scrollBox top - view boundingBox top - 
  521.         ((marker top - scrollBar top) asFloat
  522.             / scrollBar height asFloat
  523.             * view boundingBox height asFloat) rounded!
  524.  
  525. viewXDelta
  526.     "Answer an integer that indicates how much the view should be scrolled.
  527.     The scroll bar has been moved and now the view must be so the amount to
  528.     scroll is computed as a ratio of the current scroll bar position."
  529.  
  530.     ^scrollBox left - view boundingBox left
  531.         - ((xMarker left - xScrollBar left) asFloat
  532.             / xScrollBar width asFloat
  533.             * view boundingBox width asFloat) rounded!
  534.  
  535. xScrollAmount
  536.  
  537.     ^(sensor cursorPoint - scrollBar inside leftCenter) x!
  538.  
  539. xScrollView: anInteger 
  540.     "If anInteger is not zero, scroll by anInteger amount."
  541.  
  542.     | min max amount |
  543.     max _ view boundingBox left - scrollBox left min: 0.
  544.     min _ view boundingBox right - scrollBox right max: 0.
  545.     amount _ (anInteger negated max: max) min: min.
  546.     amount ~= 0
  547.         ifTrue: 
  548.             [self scrollBy: amount @ 0.
  549.             view clearInside.
  550.             view display]! !
  551.  
  552.  
  553. !GraphHolderController methodsFor: 'displaying'!
  554.  
  555. displayOn: aDisplayMedium transformation: aDisplayTransformation clippingBox: clippingBox rule: ruleInteger mask: halfTone
  556.  
  557.     | location |
  558.     location _ aDisplayTransformation applyTo: scrollBox origin x negated @ scrollBox origin y negated.
  559.     model form
  560.         displayOn: aDisplayMedium
  561.         at: location
  562.         clippingBox: clippingBox
  563.         rule: ruleInteger
  564.         mask: halfTone.
  565.     selection == nil ifFalse: [self darkHighlightSelection]! !
  566.  
  567.  
  568. !GraphHolderController methodsFor: 'private'!
  569.  
  570. darkHighlightSelection
  571.  
  572.     | selectBox  |
  573.     selectBox _ (selection boundingBox
  574.                     translateBy: selection offset +
  575.                                   model offset +
  576.                                   view displayTransformation translation -
  577.                                   scrollBox origin) rounded.
  578.     (selection form) displayOn: Display
  579.                     at: (selectBox origin)
  580.                     clippingBox: (selectBox intersect: view insetDisplayBox)
  581.                     rule: 12
  582.                     mask: Form black!
  583.  
  584. deHighlightSelection
  585.  
  586.     | selectBox  |
  587.     selectBox _ (selection boundingBox
  588.                     translateBy: selection offset +
  589.                                   model offset +
  590.                                   view displayTransformation translation -
  591.                                   scrollBox origin) rounded.
  592.     (selection form) displayOn: Display
  593.                     at: (selectBox origin)
  594.                     clippingBox: (selectBox intersect: view insetDisplayBox)
  595.                     rule: Form over
  596.                     mask: Form black!
  597.  
  598. dimHighlightSelection
  599.  
  600.     | selectBox  newForm |
  601.     selectBox _ (selection boundingBox
  602.                     translateBy: selection offset +
  603.                                   model offset +
  604.                                   view displayTransformation translation -
  605.                                   scrollBox origin) rounded.
  606.     newForm _ selection form deepCopy.
  607.     newForm fill: (newForm boundingBox)
  608.             rule: Form under
  609.             mask: Form lightGray.
  610.     newForm displayOn: Display
  611.                     at: (selectBox origin)
  612.                     clippingBox: (selectBox intersect: view insetDisplayBox)
  613.                     rule: Form over
  614.                     mask: Form black!
  615.  
  616. setSelection: aGraphNode
  617.     "Set the currently selected node to aGraphNode and set
  618.     the yellowButtonMenu."
  619.  
  620.     selection == nil
  621.         ifFalse: [self deHighlightSelection].
  622.     selection _ aGraphNode.
  623.     selection == nil
  624.         ifTrue: [yellowButtonMenu _ YellowButtonMenu]
  625.         ifFalse: [self darkHighlightSelection.
  626.                 yellowButtonMenu _ selectionMenu]!
  627.  
  628. xAndYScrollAbsolute
  629.  
  630.     | savedCursor oldMarker oldXMarker cursorPoint delta |
  631.     ((self canXScroll or: [self canScroll])
  632.             and: [sensor redButtonPressed]) ifTrue:
  633.         [savedCursor _ sensor currentCursor.
  634.         self changeCursor: Cursor fourWay.
  635.         cursorPoint _ sensor cursorPoint.
  636.         [sensor redButtonPressed and: [self isControlActive]] whileTrue:
  637.             [[(sensor cursorPoint - cursorPoint) abs < (1@1)
  638.                 and: [sensor redButtonPressed]] whileTrue.
  639.             delta _ cursorPoint.
  640.             delta _ (cursorPoint _ sensor cursorPoint) - delta.
  641.             self scrollViewXY: delta.
  642.             self moveMarker.
  643.             self moveXMarker].
  644.         savedCursor show]! !
  645.  
  646. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  647.  
  648. GraphHolderController class
  649.     instanceVariableNames: ''!
  650.  
  651.  
  652. !GraphHolderController class methodsFor: 'class initialization'!
  653.  
  654. initialize
  655.     "GraphController initialize."
  656.  
  657.     YellowButtonMenu _ ActionMenu
  658.         labels: 'inspect\file out' withCRs
  659.         selectors: #( #mvcInspect #fileOutGraph )! !
  660.  
  661.  
  662. GraphHolderController initialize!
  663. View subclass: #GraphHolderView
  664.     instanceVariableNames: ''
  665.     classVariableNames: ''
  666.     poolDictionaries: ''
  667.     category: 'Grapher'!
  668. GraphHolderView comment:
  669. 'I provide a resizable View on graphical objects, without scaling the object.  To do this I maintain the standard cooridinate transformations of View, but I use only a transformation with unit scaling for display purposes.
  670.  
  671. Used as a subview of a StandardSystemView, I should be added via the addSubView:in:borderWidth: message to ensure proper rescaling during a resize operation.
  672. '!
  673.  
  674.  
  675. !GraphHolderView methodsFor: 'initialize-release'!
  676.  
  677. release
  678.     "If the #noform change protocol has been used, there is a circularity
  679.     in the Graph so release it, too."
  680.  
  681.     model release.
  682.     super release! !
  683.  
  684.  
  685. !GraphHolderView methodsFor: 'window access'!
  686.  
  687. defaultWindow
  688.  
  689.     ^model boundingBox! !
  690.  
  691.  
  692. !GraphHolderView methodsFor: 'controller access'!
  693.  
  694. defaultControllerClass
  695.  
  696.     ^GraphHolderController! !
  697.  
  698.  
  699. !GraphHolderView methodsFor: 'display box access'!
  700.  
  701. computeBoundingBox
  702.  
  703.     ^boundingBox _ model boundingBox! !
  704.  
  705.  
  706. !GraphHolderView methodsFor: 'displaying'!
  707.  
  708. display
  709.  
  710.     self isUnlocked ifTrue:
  711.         [boundingBox _ nil.
  712.         viewport _ nil.
  713.         self controller scrollBox: self insetDisplayBox].
  714.     super display!
  715.  
  716. displayView
  717.     "We always want to see the Graph at unit scale."
  718.  
  719.     controller
  720.         displayOn: Display
  721.         transformation: self displayTransformation copy scaleOfOne
  722.         clippingBox: self insetDisplayBox
  723.         rule: Form over
  724.         mask: Form black! !
  725.  
  726.  
  727. !GraphHolderView methodsFor: 'updating'!
  728.  
  729. update: how
  730.     "Graph's change protocol includes #form and #noform.  #form indicates
  731.     that the view is actually displaying a Form and does not need to clear
  732.     its inside during scrolling.  #noform indicates that the Graph is being
  733.     redisplayed each time the View scrolls, and the View must clear its
  734.     inside before redisplaying the Graph.  The boundingBox is always reset
  735.     because the size of the Graph changed."
  736.  
  737.     how == #form ifTrue:
  738.         [boundingBox _ nil.
  739.         self insideColor: nil.
  740.         ^self].
  741.     how == #noform ifTrue:
  742.         [boundingBox _ nil.
  743.         self insideColor: Form white.
  744.         ^self]! !
  745.  
  746.  
  747. !GraphHolderView methodsFor: 'model access'!
  748.  
  749. erase
  750.  
  751.     "I replace the current model with a model constructed of the EmptyGraph."
  752.  
  753.     model isEmpty
  754.         ifFalse: [ self replaceModel: (GraphHolder createEmpty)]!
  755.  
  756. replaceModel: newModel
  757.  
  758.     "I replace the model in the view with a new model."
  759.  
  760.     self model: newModel.
  761.     self update: #noform.
  762.     self clearInside.
  763.     self display! !
  764.  
  765. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  766.  
  767. GraphHolderView class
  768.     instanceVariableNames: ''!
  769.  
  770.  
  771. !GraphHolderView class methodsFor: 'instance creation'!
  772.  
  773. openOn: roots label: labelString
  774.     "Create a Graph viewing the DAG rooted in roots.  Label the
  775.     GraphView with labelString.  The default lay out is horizontal.
  776.     See the comment in GraphView class.open:label:menu:"
  777.  
  778.     self openOn: roots label: labelString format: #( #horizontal )!
  779.  
  780. openOn: roots label: labelString format: formatSymbols
  781.     "By default, Graph windows do not respond to mouse clicks
  782.     (except for the yellow button menu)."
  783.  
  784.     self openOn: roots label: labelString format: formatSymbols menu: nil!
  785.  
  786. openOn: roots label: labelString format: formatSymbols menu: anActionMenu
  787.     "The default messages used to build a graph are #children and
  788.     #graphLabel.  #children returns a Colleciton of child nodes.
  789.     #graphLabel returns a Text to be used as the label in the GraphView."
  790.  
  791.     self openOn: roots
  792.         label: labelString
  793.         format: formatSymbols
  794.         menu: anActionMenu
  795.         childrenMsg: #children
  796.         labelMsg: #graphLabel!
  797.  
  798. openOn: roots label: labelString format: formatSymbols menu: actionMenu childrenMsg: childrenMsg labelMsg: labelMsg
  799.  
  800.     self open: (self createModel: roots
  801.                     children: childrenMsg
  802.                     label: labelMsg
  803.                     format: formatSymbols)
  804.         label: labelString
  805.         menu: actionMenu! !
  806.  
  807.  
  808. !GraphHolderView class methodsFor: 'private'!
  809.  
  810. createModel: roots children: childrenMsg label: labelMsg format: formatSymbols
  811.  
  812.     | aGraph |
  813.     aGraph _ GraphHolder createForestWithRoots: roots
  814.                     children: childrenMsg
  815.                     label: labelMsg.
  816.     aGraph layout: formatSymbols.
  817.     ^aGraph!
  818.  
  819. open: aGraph label: labelString menu: anActionMenu
  820.     "Open a scrollable, resizeable view displaying the data structure
  821.     in aGraph.  To make the elements sensitive to mouse clicks anActionMenu
  822.     non nil. The message selected from the menu will be sent to the selected
  823.     element.  If anActionMenu is nil mouse clicks are ignored."
  824.  
  825.     | formView topView |
  826.     formView _ self new model: aGraph.
  827.     formView controller selectionMenu: anActionMenu.
  828.     topView _ StandardSystemView new label: labelString.
  829.     topView borderWidth: 1.
  830.     topView insideColor: Form white.
  831.     "formView is added as follows to ensure proper scaling of
  832.     the view when the topView is resized (via 'frame')."
  833.     topView addSubView: formView in: (0@0 extent: 1@1) borderWidth: 1.
  834.     topView controller open! !
  835. #('FourWay' 'LeftCursor' 'RightCursor' 'XMarkerCursor') do:
  836.     [ :var | Cursor addClassVarName: var].!
  837.  
  838.  
  839. !Cursor class methodsFor: 'constants'!
  840.  
  841. fourWay
  842.     "Answer the instance of me that is the shape of four connected arrows."
  843.     ^FourWay! !
  844.  
  845.  
  846. !Cursor class methodsFor: 'constants'!
  847.  
  848. left
  849.     "Answer the instance of me that is the shape of an arrow facing to the left."
  850.     ^LeftCursor! !
  851.  
  852.  
  853. !Cursor class methodsFor: 'constants'!
  854.  
  855. right
  856.     "Answer the instance of me that is the shape of an arrow facing to the right."
  857.     ^RightCursor! !
  858.  
  859.  
  860. !Cursor class methodsFor: 'constants'!
  861.  
  862. xMarker
  863.     "Answer the instance of me that is displayed when thumb-scrolling on the x-axis."
  864.     ^XMarkerCursor! !
  865.  
  866.  
  867. !Cursor class methodsFor: 'class initialization'!
  868.  
  869. initialize
  870.     "Create all the standard cursors
  871.         Cursor blank
  872.         Cursor corner
  873.         Cursor crossHair
  874.         Cursor down
  875.         Cursor execute
  876.         Cursor fourWay
  877.         Cursor left
  878.         Cursor marker
  879.         Cursor normal
  880.         Cursor origin
  881.         Cursor read
  882.         Cursor right
  883.         Cursor square
  884.         Cursor up
  885.         Cursor wait
  886.         Cursor write
  887.         Cursor xMarker"
  888.  
  889.     OriginCursor _   
  890.         (Cursor
  891.             extent: 16@16
  892.             fromArray: #(
  893.         2r1111111111111111
  894.         2r1111111111111111
  895.         2r1100000000000000
  896.         2r1100000000000000
  897.         2r1100000000000000
  898.         2r1100000000000000
  899.         2r1100000000000000
  900.         2r1100000000000000
  901.         2r1100000000000000
  902.         2r1100000000000000
  903.         2r1100000000000000
  904.         2r1100000000000000
  905.         2r1100000000000000
  906.         2r1100000000000000
  907.         2r1100000000000000
  908.         2r1100000000000000)
  909.             offset: -2@-2).
  910.  
  911.     CornerCursor _ 
  912.         (Cursor 
  913.             extent: 16@16
  914.             fromArray: #(
  915.         2r0000000000000011
  916.         2r0000000000000011
  917.         2r0000000000000011
  918.         2r0000000000000011
  919.         2r0000000000000011
  920.         2r0000000000000011
  921.         2r0000000000000011
  922.         2r0000000000000011
  923.         2r0000000000000011
  924.         2r0000000000000011
  925.         2r0000000000000011
  926.         2r0000000000000011
  927.         2r0000000000000011
  928.         2r0000000000000011
  929.         2r1111111111111111
  930.         2r1111111111111111)
  931.             offset: -14@-14).
  932.  
  933.     ReadCursor _  
  934.         (Cursor
  935.             extent: 16@16
  936.             fromArray: #(
  937.         2r0000110000000110
  938.         2r0001001000001001
  939.         2r0001001000001001
  940.         2r0010000000010000
  941.         2r0100000000100000
  942.         2r1111101111100000
  943.         2r1000010000100000
  944.         2r1000010000100000
  945.         2r1011010110100000
  946.         2r0111101111000000
  947.         2r0
  948.         2r0
  949.         2r0
  950.         2r0
  951.         2r0
  952.         2r0)
  953.     offset: 0@0).
  954.  
  955.     WriteCursor _ (Cursor
  956.     extent: 16@16
  957.     fromArray: #(
  958.         2r0000000000000110
  959.         2r0000000000001111
  960.         2r0000000000010110
  961.         2r0000000000100100
  962.         2r0000000001001000
  963.         2r0000000010010000
  964.         2r0000000100100000
  965.         2r0000001001000011
  966.         2r0000010010000010
  967.         2r0000100100000110
  968.         2r0001001000001000
  969.         2r0010010000001000
  970.         2r0111100001001000
  971.         2r0101000010111000
  972.         2r0110000110000000
  973.         2r1111111100000000)
  974.     offset: 0@0).
  975.  
  976.     WaitCursor _ 
  977.           (Cursor
  978.             extent: 16@16
  979.             fromArray: #(
  980.         2r1111111111111111
  981.         2r1000000000000001
  982.         2r0100000000000010
  983.         2r0010000000000100
  984.         2r0001110000111000
  985.         2r0000111101110000
  986.         2r0000011011100000
  987.         2r0000001111000000
  988.         2r0000001111000000
  989.         2r0000010110100000
  990.         2r0000100010010000
  991.         2r0001000110001000
  992.         2r0010001101000100
  993.         2r0100111111110010
  994.         2r1011111111111101
  995.         2r1111111111111111)
  996.             offset: 0@0).
  997.  
  998.     BlankCursor _ Cursor new.
  999.  
  1000.     XeqCursor _ 
  1001.         (Cursor
  1002.             extent: 16@16
  1003.             fromArray: #(
  1004.         2r1000000000010000
  1005.         2r1100000000010000
  1006.         2r1110000000111000
  1007.         2r1111000111111111
  1008.         2r1111100011000110
  1009.         2r1111110001000100
  1010.         2r1111111001111100
  1011.         2r1111000001101100
  1012.         2r1101100011000110
  1013.         2r1001100010000010
  1014.         2r0000110000000000
  1015.         2r0000110000000000
  1016.         2r0000011000000000
  1017.         2r0000011000000000
  1018.         2r0000001100000000
  1019.         2r0000001100000000)
  1020.     offset: 0@0).
  1021.  
  1022.     SquareCursor _ 
  1023.         (Cursor
  1024.             extent: 16@16
  1025.             fromArray: #(
  1026.         2r0
  1027.         2r0
  1028.         2r0
  1029.         2r0
  1030.         2r0
  1031.         2r0000001111000000
  1032.         2r0000001111000000
  1033.         2r0000001111000000
  1034.         2r0000001111000000
  1035.         2r0
  1036.         2r0
  1037.         2r0
  1038.         2r0
  1039.         2r0
  1040.         2r0
  1041.         2r0)
  1042.     offset: -8@-8).
  1043.  
  1044.     NormalCursor _   
  1045.         (Cursor
  1046.             extent: 16@16
  1047.             fromArray: #(
  1048.         2r1000000000000000
  1049.         2r1100000000000000
  1050.         2r1110000000000000
  1051.         2r1111000000000000
  1052.         2r1111100000000000
  1053.         2r1111110000000000
  1054.         2r1111111000000000
  1055.         2r1111100000000000
  1056.         2r1111100000000000
  1057.         2r1001100000000000
  1058.         2r0000110000000000
  1059.         2r0000110000000000
  1060.         2r0000011000000000
  1061.         2r0000011000000000
  1062.         2r0000001100000000
  1063.         2r0000001100000000)
  1064.     offset: 0@0).
  1065.  
  1066.     CrossHairCursor _   
  1067.         (Cursor
  1068.             extent: 16@16
  1069.             fromArray: #(
  1070.         2r0000000100000000
  1071.         2r0000000100000000
  1072.         2r0000000100000000
  1073.         2r0000000100000000
  1074.         2r0000000100000000
  1075.         2r0000000100000000
  1076.         2r0000000100000000
  1077.         2r1111111111111110
  1078.         2r0000000100000000
  1079.         2r0000000100000000
  1080.         2r0000000100000000
  1081.         2r0000000100000000
  1082.         2r0000000100000000
  1083.         2r0000000100000000
  1084.         2r0000000100000000
  1085.         2r0)
  1086.             offset: -7@-7).
  1087.  
  1088.     MarkerCursor _ 
  1089.         Cursor
  1090.             extent: 16@16
  1091.             fromArray: #(
  1092.         2r0
  1093.         2r0
  1094.         2r0
  1095.         2r0000001000000000
  1096.         2r0000001110000000
  1097.         2r0000001111100000
  1098.         2r1111111111111000
  1099.         2r1111111111111110
  1100.         2r1111111111111000
  1101.         2r0000001111100000
  1102.         2r0000001110000000
  1103.         2r0000001000000000
  1104.         2r0
  1105.         2r0
  1106.         2r0
  1107.         2r0)
  1108.             offset: -7@-7.
  1109.  
  1110.     UpCursor _ 
  1111.         Cursor 
  1112.             extent: 16@16
  1113.             fromArray: #(
  1114.         2r1000000000000000
  1115.         2r1100000000000000
  1116.         2r1110000000000000
  1117.         2r1111000000000000
  1118.         2r1111100000000000
  1119.         2r1111110000000000
  1120.         2r1100000000000000
  1121.         2r1100000000000000
  1122.         2r1100000000000000
  1123.         2r1100000000000000
  1124.         2r1100000000000000
  1125.         2r1100000000000000
  1126.         2r1100000000000000
  1127.         2r1100000000000000
  1128.         2r1100000000000000
  1129.         2r1100000000000000)
  1130.              offset: 0@-7.
  1131.  
  1132.     DownCursor _
  1133.          Cursor 
  1134.             extent: 16@16
  1135.             fromArray: #(
  1136.         2r0000110000000000
  1137.         2r0000110000000000
  1138.         2r0000110000000000
  1139.         2r0000110000000000
  1140.         2r0000110000000000
  1141.         2r0000110000000000
  1142.         2r0000110000000000
  1143.         2r0000110000000000
  1144.         2r0000110000000000
  1145.         2r0000110000000000
  1146.         2r1111110000000000
  1147.         2r0111110000000000
  1148.         2r0011110000000000
  1149.         2r0001110000000000
  1150.         2r0000110000000000
  1151.         2r0000010000000000)
  1152.             offset: -5@-7.
  1153.  
  1154.     LeftCursor _ 
  1155.         Cursor 
  1156.             extent: 16@16
  1157.             fromArray: #(
  1158.         2r1111111111111111
  1159.         2r0111111111111111
  1160.         2r0011110000000000
  1161.         2r0001110000000000
  1162.         2r0000110000000000
  1163.         2r0000010000000000
  1164.         2r0000000000000000
  1165.         2r0000000000000000
  1166.         2r0000000000000000
  1167.         2r0000000000000000
  1168.         2r0000000000000000
  1169.         2r0000000000000000
  1170.         2r0000000000000000
  1171.         2r0000000000000000
  1172.         2r0000000000000000
  1173.         2r0000000000000000)
  1174.              offset: -7@0.
  1175.  
  1176.     RightCursor _
  1177.          Cursor 
  1178.             extent: 16@16
  1179.             fromArray: #(
  1180.         2r0000000000100000
  1181.         2r0000000000110000
  1182.         2r0000000000111000
  1183.         2r0000000000111100
  1184.         2r1111111111111110
  1185.         2r1111111111111111
  1186.         2r0000000000000000
  1187.         2r0000000000000000
  1188.         2r0000000000000000
  1189.         2r0000000000000000
  1190.         2r0000000000000000
  1191.         2r0000000000000000
  1192.         2r0000000000000000
  1193.         2r0000000000000000
  1194.         2r0000000000000000
  1195.         2r0000000000000000)
  1196.             offset: -7@-5.
  1197.     XMarkerCursor _ 
  1198.         Cursor
  1199.             extent: 16@16
  1200.             fromArray: #(
  1201.         2r0
  1202.         2r0000000100000000
  1203.         2r0000000100000000
  1204.         2r0000001110000000
  1205.         2r0000001110000000
  1206.         2r0000011111000000
  1207.         2r0000011111000000
  1208.         2r0000111111100000
  1209.         2r0000111111100000
  1210.         2r0001111111110000
  1211.         2r0000001110000000
  1212.         2r0000001110000000
  1213.         2r0000001110000000
  1214.         2r0000001110000000
  1215.         2r0000001110000000
  1216.         2r0000001110000000)
  1217.             offset: -7@-7.
  1218.     FourWay _ 
  1219.         Cursor
  1220.             extent: 16@16
  1221.             fromArray: #(
  1222.         2r0000000100000000
  1223.         2r0000001110000000
  1224.         2r0000011111000000
  1225.         2r0000111111100000
  1226.         2r0001001110010000
  1227.         2r0011001110011000
  1228.         2r0111111111111100
  1229.         2r1111111111111110
  1230.         2r0111111111111100
  1231.         2r0011001110011000
  1232.         2r0001001110010000
  1233.         2r0000111111100000
  1234.         2r0000011111000000
  1235.         2r0000001110000000
  1236.         2r0000000100000000
  1237.         2r0000000000000000)
  1238.             offset: -7@-7.
  1239.  
  1240. "Cursor initialize"! !
  1241. Cursor initialize.!
  1242.  
  1243.  
  1244.